package cn.HL.basic.service.impl;

import cn.HL.basic.constants.BaseConstant;
import cn.HL.basic.dto.RegisterDto;
import cn.HL.basic.exception.BusinessException;
import cn.HL.basic.service.IVerifyCodeService;
import cn.HL.basic.util.SmsUtils;
import cn.HL.basic.util.StrUtils;
import cn.HL.basic.util.VerifyCodeUtils;
import cn.HL.user.domain.User;
import cn.HL.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;
@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    /**
     * 图片验证码
     * @param key
     * @return
     */
    @Override
    public String image(String key) {
        if(!StringUtils.hasLength(key)){
            throw  new BusinessException("你不要搞我了");
        }
        //生成code
        String code = VerifyCodeUtils.generateVerifyCode(4);
        //存放进redis
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //生成64编码
        return VerifyCodeUtils.VerifyCode(100,40,code);
    }

    /**
     * 手机验证码
     * @param dto
     */
    @Override
    public void smsCode(RegisterDto dto) {
        String type = dto.getType();
        if(type.equals("register")){
            registerSmsCode(dto);
        }else if (type.equals("binder")){
            binderSmsCode(dto);
        }
    }


    /**
     * 注册验证码
     * @param dto
     */
    private void registerSmsCode(RegisterDto dto) {
        //获取前端传过来的数据
        //电话
        String phone = dto.getPhone();
        //存储图片验证码的key
        String imageCodeKey = dto.getImageCodeKey();
        //图片验证码
        String imageCodeValue = dto.getImageCodeValue();
        //空校验
        if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(imageCodeKey)||StringUtils.isEmpty(imageCodeValue)){
            throw new BusinessException("参数不能为空哦");
        }
        //获取redis里面的key
        Object code = redisTemplate.opsForValue().get(imageCodeKey);
        //为空
        if(code==null){
            throw new BusinessException("图形验证码过期,重新获取");
        }
        //比较图形验证码是否正确并且不区分大小写
        //不正确
        if(!code.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("图形验证码不正确,请重新填写");
        }
        //正确通过手机号查询看是否注册过
        User user = userMapper.loadByPhone(phone);
        //注册过
        if(user!=null){
            throw new BusinessException("你已经注册过,请找回密码登录");
        }
        //没注册过
        //用手机号和业务拼接
        String registerKey=phone+ BaseConstant.RegisterConstant.REGISTER_SMS_PREFIX;
        sendSmsCode(registerKey);
    }


    /**
     * 绑定验证码
     * @param dto
     */
    private void binderSmsCode(RegisterDto dto) {
        String binderKey=dto.getPhone()+ BaseConstant.RegisterConstant.BINDER_SMS_PREFIX;
        sendSmsCode(binderKey);
    }
    /**
     * 发送验证码逻辑
     * @param key
     */
    private void sendSmsCode(String key) {
        String smsCode="";
        //通过redis获取到了
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        if(smsCodeTmp!=null){
            Long oldtime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);

            //获取到了判断一下时间是否过了60秒 防止恶意
            if(System.currentTimeMillis()-oldtime<=1*60*1000){
                throw new BusinessException("滚犊子");
            }
            //到了一分钟但是没到三分钟 ,我们就继续使用之前的
            smsCode=smsCodeTmp.toString().split(":")[0];

        }else{
            //没获取到 第一次来  获取4位随机的英文字母或数字
            smsCode=StrUtils.getComplexRandomString(4);
        }
        //存储redis并设置过期时间  随机验证码+:+时间戳
        String smsCodeValue = smsCode+":"+System.currentTimeMillis();
        //存到redis里面  key 为 手机号加上:业务    value 是 随机验证码加上 : 时间戳
        redisTemplate.opsForValue().set(key,smsCodeValue,3, TimeUnit.MINUTES);
        //发送短信  一共还剩3条
        //SmsUtils.sendSms(phone,"您本次的验证码:"+smsCode+",三分钟内有效");
        System.out.println(smsCode);

    }

}
